//
//  HZKitMarco.h
//  HZCategories
//
//  Created by 红纸 on 16/6/15.
//  Copyright © 2016年 HongZhi. All rights reserved.
//

#ifndef HZKitMarco_h
#define HZKitMarco_h

//别问我为什么跟Y YKit的代码都一样 我就是准备全部敲一遍 你打我呀

#ifdef __cplusplus      //如果有此参数  告诉编译器这一段是CPP代码
#define HZ_EXTERN_C_BEGIN  extern "C" {
#define HZ_EXTERN_C_END  }
#else
#define HZ_EXTERN_C_BEGIN
#define HZ_EXTERN_C_END
#endif


HZ_EXTERN_C_BEGIN

#ifndef HZ_CLAMP // return the clamped value
#define HZ_CLAMP(_x_, _low_, _high_)  ((_low_)<(_high_))?(((_x_) > (_high_)) ? (_high_) : (((_x_) < (_low_)) ? (_low_) : (_x_))):(((_x_) > (_low_)) ? (_low_) : (((_x_) < (_high_)) ? (_high_) : (_x_)))
#endif

/**
 *  Tip
 *  __typeof__(var) 是gcc对C语言的一个扩展保留字，用于声明变量类型,var可以是数据类型（int， char*..),也可以是变量表达式。
 *  do{}while(0) 用来保证其原子性
 */
#ifndef HZ_SWAP // change a and b
#define HZ_SWAP(_a_,_b_) do { __typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = _tmp_; } while (0)
#endif

//断言
#define HZAssertNil(condition, description, ...) NSAssert(!(condition), (description), ##__VA_ARGS__)
#define HZCAssertNil(condition, description, ...) NSCAssert(!(condition), (description), ##__VA_ARGS__)

#define HZAssertNotNil(condition, description, ...) NSAssert((condition), (description), ##__VA_ARGS__)
#define HZCAssertNotNil(condition, description, ...) NSCAssert((condition), (description), ##__VA_ARGS__)

#define HZAssertMainThread() NSAssert([NSThread isMainThread], @"This method must be called on the main thread")
#define HZCAssertMainThread() NSCAssert([NSThread isMainThread], @"This method must be called on the main thread")


/**
 Add this macro before each category implementation, so we don't have to use
 -all_load or -force_load to load object files from static libraries that only
 contain categories and no classes.
 More info: http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html .
 *******************************************************************************
 Example:
    YYSYNTH_DUMMY_CLASS(NSString_YYAdd)
 */
//用来解决一些静态库的一些问题
#ifndef HZSYNTH_DUMMY_CLASS
#define HZSYNTH_DUMMY_CLASS(_name_)\
@interface HZSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation HZSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif

/**
 Synthsize a dynamic object property in @implementation scope.
 It allows us to add custom properties to existing classes in categories.
 
 @param association  ASSIGN / RETAIN / COPY / RETAIN_NONATOMIC / COPY_NONATOMIC
 @warning #import <objc/runtime.h>
 *******************************************************************************
 Example:
 @interface NSObject (MyAdd)
 @property (nonatomic, retain) UIColor *myColor;
 @end
 
 #import <objc/runtime.h>
 @implementation NSObject (MyAdd)
 YYSYNTH_DYNAMIC_PROPERTY_OBJECT(myColor, setMyColor, RETAIN, UIColor *)
 @end
 */
//给Category里面添加属性 利用关联 对象类型
#ifndef HZSYNTH_DYNAMIC_PROPERTY_OBJECT
#define HZSYNTH_DYNAMIC_PROPERTY_OBJECT(_getter_, _setter_, _association_, _type_) \
- (void)_setter_ : (_type_)object { \
[self willChangeValueForKey:@#_getter_]; \
objc_setAssociatedObject(self, _cmd, object, OBJC_ASSOCIATION_ ## _association_); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \
return objc_getAssociatedObject(self, @selector(_setter_:)); \
}
#endif

/**
 Synthsize a dynamic c type property in @implementation scope.
 It allows us to add custom properties to existing classes in categories.
 
 @warning #import <objc/runtime.h>
 *******************************************************************************
 Example:
 @interface NSObject (MyAdd)
 @property (nonatomic, retain) CGPoint myPoint;
 @end
 
 #import <objc/runtime.h>
 @implementation NSObject (MyAdd)
 YYSYNTH_DYNAMIC_PROPERTY_CTYPE(myPoint, setMyPoint, CGPoint)
 @end
 */
//给Category里面添加属性 利用关联  基础类型
#ifndef YYSYNTH_DYNAMIC_PROPERTY_CTYPE
#define YYSYNTH_DYNAMIC_PROPERTY_CTYPE(_getter_, _setter_, _type_) \
- (void)_setter_ : (_type_)object { \
[self willChangeValueForKey:@#_getter_]; \
NSValue *value = [NSValue value:&object withObjCType:@encode(_type_)]; \
objc_setAssociatedObject(self, _cmd, value, OBJC_ASSOCIATION_RETAIN); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \
_type_ cValue = { 0 }; \
NSValue *value = objc_getAssociatedObject(self, @selector(_setter_:)); \
[value getValue:&cValue]; \
return cValue; \
}
#endif


HZ_EXTERN_C_END

#endif /* HZKitMarco_h */
